// resourcemanager.cpp : contains the singleton class for resource management that is required throughout the application
//$Id: ResourceManager.cpp 48 2009-09-28 22:27:40Z brwarner2 $
#include "StdAfx.h"
#include "ResourceManager.h"

CResourceManager::CResourceManager(void) : m_pRenderDevice(0), m_pInputDevice(0), m_pAudioDevice(0), 
m_skins(), m_skinname()
{
	//Done
}

CResourceManager::~CResourceManager(void)
{
	//Call release
	Release();
}

std::fstream CResourceManager::File(const std::string &filename, std::ios_base::openmode om)
{
	return std::fstream(filename.c_str(), om);
}

bug::render::SkinPointer CResourceManager::CreateTexture(const std::string &filename)
{
	//Return if no render device
	if( !m_pRenderDevice ) return bug::render::INVALID_POINTER;

	//Check if the texture already exists
	TextureList::iterator iter = m_skins.find(filename);
	if( iter == m_skins.end() ) //Must create a new one
	{
		//Get texture manager
		bug::render::ITextureManager* pTex = m_pRenderDevice->GetTextureManager();

		//Create basic colors and material
		bug::render::Color c1 = bug::render::MakeColor(1.0f, 1.0f, 1.0f, 1.0f), c2 = bug::render::MakeColor(0.0f, 0.0f, 0.0f, 1.0f);
		bug::render::MaterialPointer mat = pTex->CreateMaterial(c1,c1,c1,c2,1.0f);

		//Create skin and texture
		bug::render::SkinPointer skin = pTex->CreateSkin(mat, true);
		bug::render::TexturePointer tex = pTex->CreateTexture(filename);
		pTex->AddTexture(skin, tex);

		//Create texture object with usage count of 1
		Texture t = { skin, tex, 1 };

		//Store it in the texture name
		m_skins[filename] = t;

		//Store in the names list
		m_skinname[skin] = filename;

		//Return skin
		return skin;
	}

	//Return it and increment usage
	iter->second.usage++;
	return iter->second.skin;
}

void CResourceManager::Release(void)
{
	//Iterate through each texture object
	TextureList::iterator iter = m_skins.begin();
	for( ; iter != m_skins.end(); iter++ )
	{
		ReleaseTextureObject(iter->second);
	}

	//Clear lists
	m_skins.clear();
	m_skinname.clear();
}

void CResourceManager::ReleaseTextureObject( const Texture& t )
{
	//Release objects
	m_pRenderDevice->GetTextureManager()->ReleaseSkin(t.skin);
	m_pRenderDevice->GetTextureManager()->ReleaseTexture(t.tex);
}

void CResourceManager::ReleaseSkin(bug::render::SkinPointer skin)
{
	//Return if no render device
	if( !m_pRenderDevice ) return ;

	try
	{
		//Get name of the texture
		std::string name = m_skinname[skin];

		//Get the structure
		Texture& t = m_skins[name];

		//Decrement usage counter
		t.usage--;

		//Check if it needs to be destroyed
		if( t.usage <= 0 )
		{
			ReleaseTextureObject(t);
			m_skins.erase(name);
			m_skinname.erase(skin);
		}
	}
	catch( const std::exception& ) { }
}

//Singleton
static CResourceManager* pSingleton = 0;
CResourceManager* Resource(void)
{
	return pSingleton;
}
void Resource( CResourceManager* pRes)
{
	pSingleton = pRes;
}